<?php
/**
 *
 * 文件下载相关接口
 * @author Calvin<hongbinfu@163.com>
 * @readme  :返回结果请使用common_response
 * @help    :具体用法请参考https://github.com/chriskacerguis/codeigniter-restserver
 * @other   :
 *          GET ---  $this->get();
 *          POST --- $this->post();
 *          PUT --- $this->put();
 *         DELETE --- $this->delete();
 */

require(APPPATH.'libraries/Mobile_Controller.php');
class Download extends Mobile_Controller{
    const STATUS_KEY="DOWNLOAD_PAGE_STATUS";
    private $_share_list = array();

    public function __construct() {
        parent::__construct ();
        $this->load->service('share_page_service');
        $this->load->service("login_service");
        $this->load->service("user_files_service");

    }

    /**
     * 获取分享列表页,检测状态
     */
    private function check_status(){
        $code = $this->input->get('code');
        if (empty($code)) {
            return $this->common_response(1003);
        }

        //存在分享密码再判断有无密码验证过
        $share_info = $this->session->userdata(self::STATUS_KEY);

        if (! empty($share_info) && $share_info['share_code'] == $code) {
            return $share_info;
        }

        $share_info = $this->share_page_service->get_share_link($code);
        if (empty($share_info)) {
            return $this->common_response(7104);
        }
        $user_id = $this->login_service->get_user_info('id');
        //判断是否是分享者本人访问
        if (! empty($user_id) && $share_info['uid'] == $user_id) {
            $this->session->set_userdata(self::STATUS_KEY,$share_info);
        }
        //如果存在密码
        if (isset($share_info['password']) && ! empty($share_info['password'])) {
            return $this->common_response(7105);
        }
        return $share_info;
    }

    /**
     * 判断是否需要校验密码
     */
    public function password_require_get(){
        $share_info = $this->check_status();
        return $this->common_response(0,NULL,array("require"=>false,"data"=>$share_info));
    }

    /**
     * 校验密码
     */
    public function password_valid_get(){
        $pwd = $this->get('password', TRUE);
        $share_code = $this->get('code', TRUE);
        if (empty($pwd) || empty($share_code)){
            return $this->common_response(1003);
        }
        $share_info = $this->share_page_service->get_share_link($share_code);
        if ($pwd == $share_info['password']) {
            $this->session->set_userdata(self::STATUS_KEY, $share_info);
            return $this->common_response(0);
        }

        return $this->common_response(1001);
    }

    /**
     * 取数据
     * pid 文件夹id,默认0为根目录
     * page 页码
     * limit 每页条数
     * by skiy
     */
    public function data_get(){
        $share_info = $this->check_status();

        $pid = (int)$this->input->get('pid');
        ($pid < 0) && $pid = 0;

        $path = array();
        //当pid不为0时，则需要分享列表中包含文件夹；
        //get_share_list($share_info['id'], $pid==0?NULL:2)
        $share_list_result = $this->share_page_service->get_share_list($share_info['id'], $pid==0?NULL:2);
        if (!$share_list_result) {
            return $this->common_response(7104);
        }

        $this->_share_list = $share_list_result;

        if ($pid > 0) {
            $rows = $this->_child_list($share_info['uid'], $pid);
        } else {
            $rows = $this->_main_list($share_info['uid']);
        }

        $data = array(
            'share_path' => $path,
            'rows'=>$rows
        );
        return $this->common_response(0,NULL,$data);
    }

    /**
     * 分享列表主页
     * pid 文件夹id,默认0为根目录
     * page 页码
     * limit 每页条数, 默认20条
     * by skiy
     */
    private function _main_list($uid) {
        if (empty($uid) || empty($this->_share_list)) {
            return;
        }

        $limit = (int)$this->get('limit');
        $limit == 0 && $limit = 20;
        $page = (int)$this->get('page');

        $folder_uuid_arr = array();
        $file_uuid_arr = array();
        //拆分文件夹和文件
        foreach ($this->_share_list as $v) {
            if ($v['type'] == 2) {
                $folder_uuid_arr[] = $v['fid'];
            } else {
                $file_uuid_arr[] = $v['fid'];
            }
        }

        $folder_exist_count = 0;
        $folder_data_arr = array();
        $file_data_arr = array();
        //文件夹id不为空
        if (! empty($folder_uuid_arr)) {
            $where = array(
                "deleted" => 0,
                "access_denied" => 0
            );
            if (count($folder_uuid_arr) == 1) {
                $where['id'] = $folder_uuid_arr[0];
            } else {
                $where['id'] = $folder_uuid_arr;
            }
            $folder_fields = "id,id as fid,name,creation_ts,modify_ts,access_denied";
            $folder_limit = $page * $limit.",".$limit;
            $folder_data_list = $this->user_files_service->get_folder_list($uid, FALSE, "", "name", "asc", $folder_fields, $where, $folder_limit);
            if (! empty($folder_data_list['rows'])) {
                $folder_data_arr = $folder_data_list['rows'];
            } else {
                $folder_data2_list = $this->user_files_service->get_folder_list($uid, FALSE, "", "name", "asc", $folder_fields, $where);
                empty($folder_data2_list['rows']) || $folder_exist_count = count($folder_data2_list['rows']);
            }

        }

        $get_folder_count = count($folder_data_arr);
        //文件id不为空, 文件夹未包含所有
        if (! empty($file_uuid_arr) &&
            ($get_folder_count < $limit)) {

            //有文件夹则填充文件数量,从0开始偏移
            if ($get_folder_count > 0) {
                $file_limit = "0,".($limit - $get_folder_count);
            } else if ($folder_exist_count === 0) {
                $file_limit = $page * $limit.",".$limit;
            } else {
                /*
                $folder_exist_page = $folder_exist_count / $limit;
                $file_get_count  = $limit - ($folder_exist_count % $limit);
                */
                $file_all_count = $page * $limit - $folder_exist_count;
                $file_limit = $file_all_count.",".$limit;
            }

            $where = array(
                "deleted" => 0,
                "access_denied" => 0
            );
            if (count($file_uuid_arr) == 1) {
                $where['id'] = $file_uuid_arr[0];
            } else {
                $where['id'] = $file_uuid_arr;
            }
            $file_data_list = $this->user_files_service->get_file_list($uid, FALSE, FALSE, "", $where,"name","asc","","", $file_limit);
            if(! empty($file_data_list['rows']))
            {
                $file_data_arr = $file_data_list['rows'];
            }
        }

        return array_merge($folder_data_arr, $file_data_arr);
    }

    /**
     * 子孙目录列表
     * @param $uid
     * @param $pid 文件夹id
     * @return array|void
     * by skiy
     */
    private function _child_list($uid, $pid) {
        //当查询文件夹时，分享列表必然存在文件夹
        $share_list_count = count($this->_share_list);  //分享的文件夹
        //无分享的文件夹
        if ($share_list_count < 1) {
            return $this->common_response(7104);
        }

        $limit = (int)$this->get('limit');
        $limit == 0 && $limit = 20;
        $page = (int)$this->get('page');

        //当前访问的文件夹是否可访问且未删除
        $p_folder = $this->share_page_service->get_folder_info($uid, $pid);
        if (! $p_folder) {
            return $this->common_response(7104);
        }
        $paths = explode(',', $p_folder['path']);
        //array_push($paths, $pid);
        $paths[] = (string)$pid;
        $in_path = FALSE;
        //文件夹是否在祖父级分享的目录里面
        foreach ($this->_share_list as $key => $value) {
            $in_path = in_array($value['fid'], $paths);
            //如果是分享的目录的子孙目录
            if ($in_path) {
                //记录路径
                foreach ($paths as $k => $v) {
                    if ($v != $value['fid']) {
                        unset($paths[$k]);
                        continue;
                    }
                    break;
                }
                //重新排序路径的id
                sort($paths);
                break;
            }
        }
        //如果不是在path目录
        if (! $in_path) {
            return $this->common_response(7104);
        }
        //取得所有文件夹的信息
        $field = "id,pid,id as fid,name,access_denied,deleted,creation_ts";
        $folders_info = $this->share_page_service->get_folder_path("", $paths, $field);
        if (! $folders_info) {
            return $this->common_response(7104);
        }

        $path[] = array("fid" =>0,"id"=>0,"name"=>"");
        foreach ($folders_info as $key => $value) {
            //如果目录有删除或者禁用
            if (($value['access_denied'] == 1) || ($value['access_denied'] == 1)) {
                return $this->common_response(7104);
            }
            unset($value['access_denied'], $value['deleted']);
            $path[] = $value;
        }

        $folder_exist_count = 0;
        $folder_data_arr = array();
        $file_data_arr = array();

        $where = array("deleted" => 0, "access_denied" => 0);
        $folder_limit = $page * $limit.",".$limit;;

        $folder_data_list = $this->user_files_service->get_folder_list($uid, $pid, "", "name", "asc", '', $where, $folder_limit);
        if (! empty($folder_data_list['rows'])) {
            $folder_data_arr = $folder_data_list['rows'];
        } else {
            $folder_data2_list = $this->user_files_service->get_folder_list($uid, $pid, "", "name", "asc", '', $where);
            empty($folder_data2_list['rows']) || $folder_exist_count = count($folder_data2_list['rows']);
        }

        $get_folder_count = count($folder_data_arr);
        //文件夹不够，则补充文件
        if ($get_folder_count < $limit) {
            //有文件夹则填充文件数量,从0开始偏移
            if ($get_folder_count > 0) {
                $file_limit = "0,".($limit - $get_folder_count);
            } else if ($folder_exist_count === 0) {
                $file_limit = $page * $limit.",".$limit;
            } else {
                $file_all_count = $page * $limit - $folder_exist_count;
                $file_limit = $file_all_count.",".$limit;
            }

            $file_data_list = $this->user_files_service->get_file_list($uid, FALSE, $pid, "", $where,"name","asc","","", $file_limit);
            if(! empty($file_data_list['rows']))
            {
                $file_data_arr = $file_data_list['rows'];
            }

        }

        $rows = array_merge($folder_data_arr, $file_data_arr);
        return $rows;

        /*不区分文件和文件夹
        $rows_db_data = $this->user_files_service->get_list($uid, $pid, "", "name", "asc", $where, "", $doc_limit);
        $rows = array();
        if(isset($rows_db_data['folders']) &&
            is_array($rows_db_data['folders'])){
            $rows = $rows_db_data['folders'];
        }
        if (isset($rows_db_data['files']) &&
            is_array($rows_db_data['files'])) {
            $rows = array_merge($rows, $rows_db_data['files']);
        }

        return $rows;
        */
    }

    public function link_get(){
        $share_info = $this->check_status();
        $id = $this->get("id",TRUE);
        $code = $this->get('code', TRUE);
        if(empty($id) || empty($code))
        {
            Common::ajax_return(1003);
        }
        //下载链接存活时间
        $download_exp = $this->config->item("download_expire_time");
        //检查对应的分享链接
        $share_res = $this->share_page_service->check_file_in_share($id,$code);
        if (empty($share_res))
        {
            Common::ajax_return(1003);
        }
        $data = $this->user_files_service->get_all_file_info($id,array("deleted" => 0, "access_denied" =>0),array(),array("type"=>2),"uid,name,size,ext_name,source_guid","","guid");
        if(empty($data) || empty($data['guid']))
        {
            Common::ajax_return(7001);
        }
        $file_guid = $data['guid'];
        $ext = ".ek";
        $file_name = $data['name']."_".$data['ext_name'].$ext;
        $test_source = "./resources/file/".$data['source_guid'].".tmp";
        //$this->share_service->update_downloaded_batch($data['uid'],array($id));
        $this->share_page_service->update_download($id,$code);
        if(ENVIRONMENT!="development")
        {
            $link_id = Common::download_link($file_guid, $code);

            $data = json_encode(array("guid"=>$file_guid,"name"=>rawurlencode($file_name)));
            $redis = new Redis();
            $connect = $redis->connect($this->config->item("host","redis"),$this->config->item("port","redis"),$this->config->item("timeout","redis"));
            if(!$connect)
            {
                Common::ajax_return(1019);
            }
            else
            {
                $this->user_files_service->update_file_info(array("id"=>$id),array("downloaded"=>1));
                $set = $redis->setex($link_id,$download_exp,$data);
                if(!$set)
                {
                    Common::ajax_return(1019);
                }
            }

            $single_file = array(array('id' => $id));
            Traces::trace_download_batch($single_file, Traces::EVENT_DOWNLOAD_SECURE_FILE);
            Common::ajax_return(0,NULL,array("url"=>"/d?id=".$link_id),FALSE);
        }
        //本地测试环境
        else if(file_exists($test_source))
        {
            Common::ajax_return(0,NULL,array("url"=>"/test/download?id=".$data['source_guid']."&name=".urlencode($file_name)),FALSE);
        }
        else
        {
            Common::ajax_return(1004);
        }
    }
}